﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using Indexador;
using Persistencia;
using SearchServer.Exceptions;

namespace SearchServer.AppManager
{
    public class FileSystemElementManager
    {
        private FileSystemElementPersistence _indexadorFSE;
        private IIndexadorMgr _indexadorMgr = new IndexadorMgr();

        public FileSystemElementManager()
        {
            _indexadorFSE = new FileSystemElementPersistence();
            _indexadorMgr.InicializarIndexador();
        }


        public static FileSystemElementManager GetInstancia()
        {
            return new FileSystemElementManager();
        }
        public List<FileSystemElement> BuscarFileSystemElements(String textSearch)
        {
            try
            {
                return _indexadorFSE.BuscarFSE(textSearch);
            }
            catch (DataException)
            {
                throw new BusinessException(BusinessException.ERROR_BD);
            }
        }

        public void DesIndexarFileSystemElement(int idFsElement)
        {
            try
            {
                FileSystemElement fsElement = ObtenerFileSystemElement(idFsElement);
                bool monitoreado = fsElement.Monitoreado;
                if (fsElement.Is_File)
                {
                    _indexadorFSE.EliminarFileSystemElement(idFsElement);
                    _indexadorMgr.EliminarElemento(fsElement);
                }
                else
                {
                    _indexadorFSE.EliminarFileSystemElement(idFsElement);
                    String pathCarpeta = @fsElement.Path + @"\" + @fsElement.Nombre;
                    List<FileSystemElement> elementosAnidados = _indexadorFSE.BuscarFSE(pathCarpeta);
                    foreach (FileSystemElement fileSystemElement in elementosAnidados)
                    {
                        _indexadorFSE.EliminarFileSystemElement(fileSystemElement.Id);
                        _indexadorMgr.EliminarElemento(fileSystemElement);
                    }
                }
                if (monitoreado)
                {
                    FileSystemWatcherManager.GetInstance().EliminarFileSystemWatcher(idFsElement);
                }
            }
            catch (DataException)
            {
                throw new BusinessException(BusinessException.ERROR_BD);
            }
        }

        public FileSystemElement ObtenerFileSystemElement(int idFsElement)
        {
            return _indexadorFSE.ObtenerFileSystemElement(idFsElement);
        }

        public List<FileSystemElement> ObtenerFileSystemElementsMonitoreados()
        {
            try
            {
                return _indexadorFSE.GetFileSystemElementsMonitoreados();
            }
            catch (DataException)
            {
                throw new BusinessException(BusinessException.ERROR_BD);
            }
        }

        public void IndexarFileSystemElement(FileSystemElement fsElement)
        {
            try
            {
                fsElement.Monitoreado = true;

                if (fsElement.Is_File)
                {
                    String archivo = @fsElement.Nombre + @"." + @fsElement.Extension;
                    FileInfo fileInfo = new FileInfo(archivo);
                    if (fileInfo.Exists)
                    {
                        fsElement = _indexadorFSE.InsertarFileSystemElement(fsElement);
                        _indexadorMgr.IndexarElemento(fsElement);
                        FileSystemWatcherManager.GetInstance().CrearFileSystemWatcher(fsElement);
                    }
                }
                else
                {
                    String pathCarpeta = @fsElement.Path + @"\" + @fsElement.Nombre;
                    DirectoryInfo directorioPrincipal = new DirectoryInfo(pathCarpeta);
                    if (directorioPrincipal.Exists)
                    {
                        fsElement = _indexadorFSE.InsertarFileSystemElement(fsElement);
                        _indexadorMgr.IndexarElemento(fsElement);
                        FileSystemWatcherManager.GetInstance().CrearFileSystemWatcher(fsElement);
                        //recorro los archivos
                        FileInfo[] archivos = directorioPrincipal.GetFiles();
                        foreach (var archivo in archivos)
                        {
                            FileSystemElement file = new FileSystemElement();
                            file.Extension = archivo.Extension;
                            file.Nombre = archivo.Name;
                            file.Tamaño = Convert.ToInt32(archivo.Length);
                            file.Path = archivo.DirectoryName;
                            file.Fecha_Creacion = GetFechaCreacion();
                            file.Is_File = true;
                            file.Tiene_Subcarpetas = false;
                            file.Usuario_Creacion = fsElement.Usuario_Creacion;
                            file.Monitoreado = false;
                            _indexadorFSE.InsertarFileSystemElement(file);
                            _indexadorMgr.IndexarElemento(file);
                        }
                        //recorro los directorios
                        if (fsElement.Tiene_Subcarpetas)
                        {
                            DirectoryInfo[] directorios = directorioPrincipal.GetDirectories();
                            foreach (var directorio in directorios)
                            {
                                FileSystemElement fseFolder = new FileSystemElement();
                                fseFolder.Extension = "";
                                fseFolder.Nombre = directorio.Name;
                                fseFolder.Tamaño = 0;
                                if (directorio.Parent != null) fseFolder.Path = directorio.Parent.FullName;
                                fseFolder.Fecha_Creacion = GetFechaCreacion();
                                fseFolder.Is_File = false;
                                fseFolder.Tiene_Subcarpetas = true;
                                fseFolder.Usuario_Creacion = fsElement.Usuario_Creacion;
                                fseFolder.Monitoreado = false;
                                IndexarFileSystemElement(fseFolder);
                            }
                        }
                    }
                }
            }
            catch (DataException)
            {
                throw new BusinessException(BusinessException.ERROR_BD);
            }
        }

        public void ModificarIndexadoDeFileSystemElement(int idFileSystemElementOriginal, FileSystemElement fsElement)
        {
            try
            {
                FileSystemElement original = _indexadorFSE.ObtenerFileSystemElement(idFileSystemElementOriginal);
                fsElement.Monitoreado = original.Monitoreado;
                if (fsElement.Is_File)
                {
                    //_indexadorFSE.ModificarFileSystemElement(idFileSystemElementOriginal, fsElement);
                    _indexadorMgr.ModificarElemento(original,fsElement);
                    if (original.Monitoreado)
                    {
                        FileSystemWatcherManager.GetInstance().ModificarFileSystemWatcher(idFileSystemElementOriginal, fsElement);
                    }
                }
                else
                {
                    String pathCarpeta = @fsElement.Path + @"\" + @fsElement.Nombre;
                    DirectoryInfo directorioPrincipal = new DirectoryInfo(pathCarpeta);
                    if (directorioPrincipal.Exists)
                    {
                        pathCarpeta = original.Path + @"\" + original.Nombre;
                        _indexadorFSE.EliminarFileSystemElement(idFileSystemElementOriginal);
                        if (original.Monitoreado)
                        {
                            FileSystemWatcherManager.GetInstance().EliminarFileSystemWatcher(original.Id);
                        }
                        List<FileSystemElement> elementosAnidados = _indexadorFSE.BuscarFSE(pathCarpeta);
                        foreach (FileSystemElement fileSystemElement in elementosAnidados)
                        {
                            _indexadorFSE.EliminarFileSystemElement(fileSystemElement.Id);
                            _indexadorMgr.EliminarElemento(fileSystemElement);
                        }

                        FileSystemElement fse = new FileSystemElement();

                        fse.Extension = fsElement.Extension;
                        fse.Nombre = fsElement.Nombre;
                        fse.Is_File = fsElement.Is_File;
                        fse.Tiene_Subcarpetas = false;
                        fse.Tamaño = fsElement.Tamaño;
                        fse.Path = fsElement.Path;
                        fse.Fecha_Creacion = fsElement.Fecha_Creacion;
                        fse.Usuario_Creacion = fsElement.Usuario_Creacion;
                        fse.Monitoreado = fsElement.Monitoreado;
                        IndexarFileSystemElement(fse);
                    }
                }
            }
            catch (DataException)
            {
                throw new BusinessException(BusinessException.ERROR_BD);
            }
        }

        /// <summary>
        /// Obtiene la fecha del sistema.
        /// </summary>
        /// <returns></returns>
        private static DateTime GetFechaCreacion()
        {
            TimeMgr.TimeMgr mgr = new TimeMgr.TimeMgr();
            return mgr.ObtenerFecha();
        }
    }
}